#!/usr/bin/python

import baseserver
import sys
import error
import socket
import time

DBG = True

def DEBUG(string, *argv):
    if DBG == True:
        print time.ctime(), string, argv


class NSEvent(baseserver.Event):
    """
    """
    MAXLENGTH = 2048   # MAX data length receive from client
    
    # If NServer have not received within 'TIMEOUT' seconds of any data,
    # It will disconnect with client without any warning 
    TIMEOUT = 1000.0      
    
    def __init__(self):
        baseserver.Event.__init__(self)
        
    def handler(self, request, address):
        """Dealing with connections
        """
        Trid = 0
        while True:
            request.settimeout(self.TIMEOUT)
            
            # Receive data
            try:
                data = request.recv(self.MAXLENGTH)
                DEBUG(address, 'receive', data)
            except socket.timeout:                       
                DEBUG(address, "GET data timeout: ")
                self._disconnect(request, address)
            except:
                DEBUG(address, 'Unexpected error:', sys.exc_info()[0])
                raise

            # Analyze data
            try:
                trid, response = self._analyze(request, data)
            except error.IMError, e:                    
                DEBUG(address, "Expected Error: ", e.errno, e.description)
                if not e.errno == None:
                    request.send(e.errno)
                self._disconnect(request, address)



        
    def _analyze(self, request, data):
        data = data.split(' ')
        DEBUG('Analyze', data)
        
        if data[0] == '' or len(data) < 2:
            raise error.IMError(200)               
        try:
            if int(data[1]) < 5:
                self._deallogin(request, data)
            elif int(data[1]) >= 5:
                self._presence(request, data)
        except ValueError:
            raise error.IMError(200)               # Syntax error
        except error.IMError:
            raise


    def _deallogin(self, request, data):
        currtrid = int(data[1])
        command = data[0]

        response = ''
        DEBUG('Trid is', trid)
        
        if currtid == 1 and self.Trid == 0:           
            pass
        else:
            sub = currtid - self.Trid
            if not sub == 1:
                DEBUG('Trid Error...')
                raise error.IMError(200)
        self.Trid = currtid
            
        if command == 'VER':
            response = ' '.join(data)
        elif command == 'CVR':
            response = 'CVR 2 6.0.0602 6.0.0602 1.0.0000 http://download.microsoft.com/download/8/a/4/8a42bcae-f533-4468-b871-d2bc8dd32e9e/SETUP9x.EXE http://messenger.msn.com\r\n'
        elif command == 'USR':
            if data[3] == 'I':
                result = self._auth(data[4])
                if not result == True:               
                    raise error.IMError(result)
                response = 'USR 3 TWN S lc=1033,id=507,tw=40,fs=1,ru=http%3A%2F%2Fmessenger%2Emsn%2Ecom,ct=1062764229,kpp=1,kv=5,ver=2.1.0173.1,tpf=43f8a4c8ed940c04e3740be46c4d1619\r\n'
            else:
                response = 'USR 4 OK example@passport.com example%20display%20name 1 0\r\n'
        DEBUG('Response is: ', response)
        request.send(response)

        

    def _auth(self, username):
        return True

    def _presence(self, request, data):
        pass


    def _disconnect(self, req, addr):
        DEBUG(addr, "Disconnect :")
        
        while True:
            try:
                req.close()
                break
            except:
                DEBUG(addr, "Disconnect Error, Try again...")
        sys.exit(0)

        
class NServer:
    def __init__(self, ip, port):
        self.server = baseserver.BaseServer(ip, port)
        self.event = NSEvent()

    def run(self):
        while True:
            self.server.start(self.event)
        
if __name__ == '__main__':
    import sys
    nserver = NServer(sys.argv[1], int(sys.argv[2]))
    nserver.run()
